'use strict';

const UUID = require('uuid').v4;
const svgCaptcha = require('svg-captcha');
const BaseService = require('./base');
const ParamsException = require('../exception/params');
const crypto = require('crypto');
const BadRequestException = require('../exception/bad-request');
const NotFoundException = require('../exception/not-found');

class AdminUserService extends BaseService {
  async getUserList (requestBody) {
    const { AdminUser, AdminRoleUser } = this.app.model;
    if(requestBody.all===true){
      const res = await AdminUser.findAndCountAll({
        attributes:  [ 'id', 'username','avatar'] 
      })
      return res.rows
    }else {
      const params = this.app._.cloneDeep(requestBody);
      const { count, rows } = await AdminUser.findAndCountAll({
        distinct: true,
        where: this.queryWhere(params),
        attributes: { exclude: [ 'delete_time', 'password' ] },
        include: [
          {
            model: AdminRoleUser,
            as: 'roles',
            attributes: [ 'user_id', 'role_id' ],
          },
        ],
        ...this.pageParam(params),
      });
      return this.paginate(count, rows,params);
    }
    
  }

  queryWhere (params) {
    const { Op } = this.app.Sequelize;
    const where = {}; 
    const searchType = Number(params.searchType)
    const timeType = Number(params.timeType)
    const gender = parseInt(params.gender)
    const status = parseInt(params.status);
    const searchWord =params.searchWord
    const sumTime =params.sumTime
    if(searchType === 1 && searchWord!==''){
      where[Op.and] = { username: { [Op.like]: `%${searchWord}%` } }
    }else if(searchType === 2 && searchWord!==''){
      where[Op.and] = { mobile: { [Op.like]: `%${searchWord}%` } }
    }

    if(timeType === 1 && sumTime[0]!==''&&sumTime[1]!==''){
      where[Op.and] = { create_time: { [Op.between]: [sumTime[0],sumTime[1]] } }
    }else if(timeType === 2 && sumTime[0]!==''&&sumTime[1]!==''){
      where[Op.and] = { update_time: { [Op.between]: [sumTime[0],sumTime[1]] } }
    }else if(timeType === 3 && sumTime[0]!==''&&sumTime[1]!==''){
      where[Op.and] = { last_login_time: { [Op.between]: [sumTime[0],sumTime[1]] } }
    }
    if (!isNaN(status) && [ 1, 2 ].includes(status)) {
      where.status = status;
    }
    if (!isNaN(gender) && [ 0 ,1, 2 ].includes(gender)) {
      where.gender = gender;
    }
    return where;
  }
  
  // 注册
  async register(params){
    const model = this.app.model.AdminUser;
    const user = await model.findOne({ where: { username: params.username } });
    if (user !== null) {
      throw new ParamsException('用户名已存在');
    }
    params.password = this.encryptPassword(params.password);
    params.create_time = new Date();
    params.gender = 0,
    params.status = 1,
    params.avatar = '/init/avatar.jpg'
    const newUser = await model.create(params);
    const user_id = newUser.dataValues.id
    // 初始化权限
    this.app.model.AdminRoleUser.create({user_id,role_id:8})
  }
  // 新建用户
  async createUser (params) {
    const model = this.app.model.AdminUser;
    const user = await model.findOne({ where: { username: params.username } });
    if (user !== null) {
      throw new ParamsException('用户名已存在');
    }
    const mobileUser = await model.findOne({ where: { mobile: params.mobile } });
    if (mobileUser !== null) {
      throw new ParamsException('手机号码重复');
    }
    const regEmail = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$/
    if(!regEmail.test(params.email)){
      throw new ParamsException('邮箱格式不正确')
    }
    if(params.password && params.password!==''){
      params.password = this.encryptPassword(params.password);
    }else{
      params.password = this.encryptPassword('abcd123456');//初始密码
    }
    params.create_time = new Date();
    params.avatar = '/init/avatar.jpg'
    await model.create(params);
  }

  async updateUser (params) {
    const model = this.app.model.AdminUser;
    const user = await this.findUser(params.id);
    let isHasUser = await model.findOne({ where: { username: params.username } });
    if(isHasUser && isHasUser.dataValues.id == params.id) isHasUser = null
    if (isHasUser !== null) {
      throw new ParamsException('用户名已存在');
    }
    let mobileUser = await model.findOne({ where: { mobile: params.mobile } });
    if(mobileUser && mobileUser.dataValues.id == params.id) mobileUser = null
    if (mobileUser !== null) {
      throw new ParamsException('手机号码重复');
    }
    user.username = params.username;
    user.email = params.email;
    user.mobile = params.mobile;
    user.status = params.status;
    user.gender = params.gender;
    await user.save();
  }

  // 批量删除
  async deleteUsers (ids) {
    const { Op } = this.app.Sequelize;
    await this.app.model.AdminUser.destroy({
      where:{
        id:{
          [Op.in]:ids
        }
      }
    })
  }

  async getUserInfo (userId) {
    const user = await this.findUser(userId);
    const QueryTypes = this.app.Sequelize.QueryTypes;
    const roles = await this.app.model.query('SELECT `id`,`name` FROM `admin_role` WHERE (  `id` IN (SELECT `role_id` FROM `admin_role_user` WHERE  `user_id` = :userId) ) AND `admin_role`.`delete_time` IS NULL', { type: QueryTypes.SELECT, replacements: { userId } });
    const roleIds = roles.map(item => item.id);
    let menu = [];
    if (roleIds.includes(1)) {
      menu = await this.app.model.AdminMenu.findAll({ order: [[ 'sort', 'ASC' ], [ 'id', 'ASC' ]], attributes: { exclude: [ 'delete_time' ] } });
    } else {
      if (roleIds.length === 0) {
        throw new BadRequestException(20022, '用户未绑定角色');
      }
      menu = await this.app.model.query('SELECT * FROM `admin_menu` WHERE (  `id` IN (SELECT `menu_id` FROM `admin_role_menu` WHERE  `role_id` IN (:roleIds)) ) AND `admin_menu`.`delete_time` IS NULL ORDER BY `sort` ASC, `id` DESC ', { type: QueryTypes.SELECT, replacements: { roleIds } });
    }
    user.dataValues.roles = roles;
    user.dataValues.menus = menu;
    return user;
  }

  async changeStatus(params){
    const users = await this.findUsers(params.ids);
    const updateStatus = []
    const length = users.length;
    for(let i = 0;i<length;i++){
      const id = users[i].get('id')
      const status = users[i].get('status')
      let newStatus = status == 1?2:1
      updateStatus.push({id,status:newStatus})
    }
    if(updateStatus.length){
      await this.app.model.AdminUser.bulkCreate(updateStatus,{updateOnDuplicate:['id','status']})
    }
  }

  async findUsers(userIds){
    const { Op } = this.app.Sequelize;
    const users = await this.app.model.AdminUser.findAll({
      where: {
        id: {[Op.in]: userIds}
      }
    });
    return users
  }
  
  async findUser (userId) {
    const user = await this.app.model.AdminUser.findOne({ where: { id: userId }, attributes: { exclude: [ 'delete_time' ] } });
    if (user === null) {
      throw new NotFoundException('用户不存在', 20000);
    }
    return user;
  }

  async login (params) {
    // 校验验证码
    await this.validCaptcha(params.captcha_token, params.captcha);
    let user = await this.app.model.AdminUser.findOne({ where: { username: params.username } });
    if (user === null) {
      user = await this.app.model.AdminUser.findOne({ where: { mobile: params.username } });
    }
    if (user === null) {
      throw new BadRequestException(20001, '账号密码不匹配');
    }
    if (user.password !== this.encryptPassword(params.password)) {
      throw new BadRequestException(20001, '账号密码不匹配');
    }
    if (user.status === 2) {
      throw new BadRequestException(20002, '用户已禁用');
    }
    await this.app.model.AdminUser.update({ last_login_time: new Date() }, { where: { id: user.id } });
    return await this.ctx.service.jwt.awardToken(user.id);
  }

  encryptPassword (password) {
    const key = this.md5Encrypt('12345654321');
    const pass = this.md5Encrypt(password);
    return this.md5Encrypt(pass + key);
  }

  md5Encrypt (str) {
    return crypto.createHash('md5').update(str).digest('hex');
  }

  async createCaptcha () {
    const token = UUID();
    const captcha = svgCaptcha.create({
      size: 5,
      ignoreChars: '0o1il',
      background: '#ffffff',
      width: 120,
      height: 36,
    });
    const cacheData = {
      code: captcha.text,
      times: 0,
    };
    await this.app.redis.set(token, JSON.stringify(cacheData), 'ex', 300);
    return {
      text: captcha.text,
      token,
      code: captcha.data,
    };
  }
  async validCaptcha (token, text) {
    let captcha = await this.app.redis.get(token);
    if (!captcha) {
      throw new ParamsException('验证码不正确');
    }
    captcha = JSON.parse(captcha);
    if (!captcha.code) {
      throw new ParamsException('验证码不正确');
    }
    if (text.toLowerCase() !== captcha.code.toLowerCase()) {
      let times = captcha.times;
      times += 1;
      if (times >= 5) {
        await this.app.redis.del(token);
      } else {
        captcha.times = times;
        const ttl = this.app.redis.ttl(token);
        if (ttl > 1) {
          await this.app.redis.set(token, JSON.stringify(captcha), 'ex', parseInt(ttl));
        }
      }
      throw new ParamsException('验证码不正确');
    }
    await this.app.redis.del(token);
    return true;
  }

  // 绑定角色
  async bindRoles(body){
    const {id,role_ids} = body
    let saveData = []
    const user = await this.findUser(id)
    if(role_ids.length>0){
      const roles = await this.app.model.AdminRole.findAll({
        where:{id:role_ids},
        attributes:['id']
      })
      const roleIds = roles.map(item=>item.id)
      if(roleIds.length>0){
        saveData = roleIds.map(item=>{
          return {
            user_id:user.id,
            role_id:item,
          }
        })
      }
    }
    const t = await this.app.model.transaction();
    try{
      // 先删除原有角色
      await this.ctx.model.AdminRoleUser.destroy({
        where:{user_id:user.id}
      })
      //  绑定新角色
      if(role_ids.length>0){
        await this.ctx.model.AdminRoleUser.bulkCreate(saveData)
      }
      await t.commit()
    }catch(e){
      await t.rollback()
    }
  } 


  // 根据 id 获取用户绑定的角色
  async userRoles(id){
    const Op = this.app.Sequelize.Op
    const roles = await this.ctx.model.AdminRole.findAll({
      where:{
        id:{
          [Op.in]:this.app.model.literal(`(SELECT role_id FROM admin_role_user WHERE user_id = ${id})`)
        },
      },
      attributes:['id','name','remarks']
    })
    return roles
  }

  // 修改头像
  async updateAvatar(body){
    const {id, avatar} =body
    await this.ctx.model.AdminUser.update({avatar},{
      where:{
        id
      },
    })
  }

  // 修改用户名
  async updateUsername(body){
    const {id, username} =body
    await this.ctx.model.AdminUser.update({username},{
      where:{
        id
      },
    })
  }
  // 修改密码
  async updatePsd(body){
    const {id,password,newPassword} = body
    const user = await this.ctx.model.AdminUser.findOne({
      where:{id}
    })
    if (user.password !== this.encryptPassword(password)) {
      throw new BadRequestException(20001, '密码错误');
    }
    await this.ctx.model.AdminUser.update({passsword:newPassword},{
      where:{
        id
      },
    })
  }
  // 修改其他信息
  async updateOtherMsg(body){
    const {id,mobile,gender,email,introduction} = body
    await this.ctx.model.AdminUser.update({
      mobile,gender,email,introduction
    },{
      where:{id}
    })
  }
}

module.exports = AdminUserService;
